#ifndef COMMAND_AUDIO_COMMAND_H_
#define COMMAND_AUDIO_COMMAND_H_

//this commad file declare the
//UDP Audio command 

#include "ctType.h"

#ifdef _WIN32
#pragma warning( push )
#pragma warning( disable : 4200 )
#endif

#pragma pack(1)
namespace AudioCmd
{
        //Cmd define
        enum {
                CMD_AUDIO_NULL	                        = 0x10,
                CMD_AUDIO_JOIN_ROOM                     = 0x11,	        // (rtp/rtcp) add user to room
                CMD_AUDIO_LEAVE_ROOM                    = 0x12,	        // (rtp/rtcp) del user from room
                CMD_AUDIO_FORWARD                       = 0x13,         // (rtp/rtcp) forward/receive audio stream data (old)
                CMD_AUDIO_HEART_BEAT                    = 0x14,         // (rtp/rtcp) client->server->client
                CMD_AUDIO_FORWARD_NEW                   = 0x15,         // (rtp/rtcp) forward/receive audio stream data (new)
                CMD_AUDIO_LOST_PACKET_RATE_REQ          = 0x16,         // (rtp/rtcp) request lost packet rate
                CMD_AUDIO_LOST_PACKET_RATE_RES          = 0x17,         // (rtp/rtcp) response lost packet rate
                CMD_AUDIO_LOST_PACKET_RESEND_REQ        = 0x18,         // (rtp/rtcp) request resend lost packet(C<->S)
                CMD_AUDIO_FORWARD_NEW_NEW               = 0x19,         // (rtp/rtcp) forward/receive audio stream data (new new)
                CMD_AUDIO_VIDEO_SYNC                    = 0x1a,         // (rtp) audio-video sync.
                //can not over 255
        };

        //UDP Package Head
        struct stUDPPkgHead
        {
                stUDPPkgHead()
                {
                        type_ = CMD_AUDIO_NULL;
                        room_id_=0;
                }
                stUDPPkgHead(BYTE cmd):
                        type_(cmd)
                {
                        room_id_=0;
                }
                BYTE  type_;
                DWORD room_id_;
        };

        //user request add audio server
        struct stUDPJoinRoom :
                stUDPPkgHead
        {
                stUDPJoinRoom():
                        stUDPPkgHead(CMD_AUDIO_JOIN_ROOM)
                {
                        user_id_ = 0;
                }
                DWORD user_id_;
        };

        //user request leave audio server
        struct stUDPLeaveRoom :
                stUDPPkgHead
        {
                stUDPLeaveRoom():
                        stUDPPkgHead(CMD_AUDIO_LEAVE_ROOM)
                {
                        user_id_ = 0;
                }
                DWORD user_id_;
        };

        //user forward RTP/RTCP pkg to Audio Server
        //user recv RTP/RTCP pkg from Audio Server
        struct stUDPForwardRoom :
                stUDPPkgHead
        {
                stUDPForwardRoom():
                        stUDPPkgHead(CMD_AUDIO_FORWARD)
                {
                        user_id_ = 0;
                        proto_type_ = eUDPProtoType_null;
                        data_type_ = eUDPDataType_audio;
                        data_size_ = 0;
                }
                DWORD user_id_;
                BYTE  proto_type_;      //RTP/RTCP
                BYTE  data_type_;       //audio/vedio
                DWORD data_size_;
                BYTE  data[0];          //RTP/RTCP data
                DWORD getSize() 
                {
                        return sizeof(*this)+data_size_*sizeof(data[0]); 
                }
        };

        //client send heart beat signal to server
        //server return the same signal to client
        //client use this command caculate time delay
        struct stUDPHeartBeat:
                stUDPPkgHead
        {
                stUDPHeartBeat():
                        stUDPPkgHead(CMD_AUDIO_HEART_BEAT)
                {
                        user_id_ = 0;
                        time_stamp_ = 0;
                }
                DWORD user_id_;
                QWORD time_stamp_; //ms
        };
        struct stUDPForwardRoomNew:
                stUDPPkgHead
        {
                stUDPForwardRoomNew():
                        stUDPPkgHead(CMD_AUDIO_FORWARD_NEW)
                {
                        user_from_ = 0;
                        user_to_   = 0;
                        proto_type_= eUDPProtoType_null;
                        data_type_ = eUDPDataType_audio;
                        data_size_ = 0;
                }
                DWORD user_from_;
                DWORD user_to_;
                BYTE  proto_type_;      //RTP/RTCP
                BYTE  data_type_;       //audio/vedio
                DWORD data_size_;
                BYTE  data[0];          //RTP/RTCP data
                DWORD getSize() 
                {
                        return sizeof(*this)+data_size_*sizeof(data[0]); 
                }
        };
        struct stUDPForwardRoomNewNew:
                stUDPPkgHead
        {
                stUDPForwardRoomNewNew():
                        stUDPPkgHead(CMD_AUDIO_FORWARD_NEW_NEW)
                {
                        user_from_ = 0;
                        reserve_   = 0;
                        proto_type_= eUDPProtoType_null;
                        data_type_ = eUDPDataType_audio;
                        lost_count_ = 0;
                        data_size_ = 0;
                }
                DWORD user_from_;
                DWORD reserve_;
                BYTE  proto_type_;      //RTP/RTCP
                BYTE  data_type_;       //audio/vedio
                BYTE  lost_count_;      //lost packet count of previous linker. (ie.do not need resend count).
                DWORD data_size_;
                BYTE  data[0];          //RTP/RTCP data
                DWORD getSize() 
                {
                        return sizeof(*this)+data_size_*sizeof(data[0]); 
                }
        };
        struct stUDPLostPacketRateReq:
                stUDPPkgHead
        {
                stUDPLostPacketRateReq():
                        stUDPPkgHead(CMD_AUDIO_LOST_PACKET_RATE_REQ)
                {
                        user_id_ = 0;
                        data_type_ = eUDPDataType_audio;
                        size_ = 0;
                }

                DWORD user_id_;         // requester id
                BYTE data_type_;        // audio(video)
                WORD size_;             // lost packet's user num

                struct {
                        DWORD user_id_; // lost packet's user id
                } list_[0];
                DWORD getSize()
                {
                        return sizeof(*this) + size_*sizeof(list_[0]);
                }
        };
        struct stUDPLostPacketRateRes:
                stUDPPkgHead
        {
                stUDPLostPacketRateRes():
                        stUDPPkgHead(CMD_AUDIO_LOST_PACKET_RATE_RES)
                {
                        user_id_ = 0;
                        data_type_ = eUDPDataType_audio;
                        size_ = 0;
                }

                DWORD user_id_;         // requester id
                BYTE data_type_;        // audio(video)
                WORD size_;             // lost packet's user num

                struct {
                        DWORD user_id_; // lost packet's user id
                        WORD lost_rate_; // lost packet rate
                } list_[0];
                DWORD getSize()
                {
                        return sizeof(*this) + size_*sizeof(list_[0]);
                }
        };

        //request resender packets.
        struct stUDPLostPacketResendReq:
                stUDPPkgHead
        {
                stUDPLostPacketResendReq():
                        stUDPPkgHead(CMD_AUDIO_LOST_PACKET_RESEND_REQ)
                {
                        data_type_      = eUDPDataType_audio;
                        requester_id_   = 0;
                        stream_from_    = 0;
                        seq_begin_      = 0;
                        seq_end_        = 0;
                }
                BYTE    data_type_;             //audio or video. see:eUDPDataType
                DWORD   requester_id_;          //requester id
                DWORD   stream_from_;           //audio(video) stream's sender.
                DWORD   seq_begin_;             //need resend seq: [seq_begin_, seq_end_]
                DWORD   seq_end_;
        };

        //audio-video sync packet.
        struct stUDPAVSyncPacket:
                stUDPPkgHead
        {
                stUDPAVSyncPacket():
                        stUDPPkgHead(CMD_AUDIO_VIDEO_SYNC)
                {
                        user_from_      = 0;
                        user_to_        = 0;
                        data_type_      = eUDPDataType_audio;
                        timestamp_      = 0;
                        ntp_time_       = 0;
                }
                DWORD   user_from_;
                DWORD   user_to_;
                BYTE    data_type_;             //audio or video. see:eUDPDataType
                DWORD   timestamp_;
                QWORD   ntp_time_;
        };
};
#define UDP_PKG_LEN sizeof(AudioCmd::stUDPPkgHead)
#pragma pack()

#ifdef _WIN32
#pragma warning( pop )
#endif

#endif //COMMAND_AUDIO_COMMAND_H_
